#include "HiranipraShared.h"

#ifndef _SHARED_MATH_PLANE_H_
#define _SHARED_MATH_PLANE_H_

namespace Hiranipra {
	namespace Math {

		//////////////////////////////////////////////////////////////////////////
		// Class: Plane
		//========================================================================
		class Plane
		{
		public:
			Vector	Normal;
			float	Distance;

			Plane( float A = 1, float B = 0, float C = 0, float D = 0 ) :
				Normal(A, B, C), Distance(D)
			{
			}
			
			Plane( const Vector& normal, float D = 0 ) :
				Normal(normal), Distance(D)
			{
			}

			Plane( const Plane& plane ) :
				Normal(plane.Normal), Distance(plane.Distance)
			{
			}

			Plane( const Vector& vertexA, const Vector& vertexB, const Vector& vertexC )
			{
				Vector	normalA( (vertexC - vertexA) | 1.0 );
				Vector	normalB( (vertexC - vertexB) | 1.0 );
				Distance	= -vertexA % (Normal = (normalA ^ normalB) | 1.0);
			}

			const Plane& operator = ( const Plane& plane )
			{
				Normal	= plane.Normal;
				Distance	= plane.Distance;
				return( (*this) );
			}

			// Boolean Operators
			const bool operator == ( const Plane& plane ) const
			{
				return( (Normal == plane.Normal) && (Distance == plane.Distance) );
			}
			const bool operator != ( const Plane& plane ) const
			{
				return( !( (*this) == plane ) );
			}

			// Move plane
			const Plane operator + ( const Vector& vector ) const
			{
				return( Plane(Normal, Distance + vector % Normal) );
			}
			const Plane& operator += ( const Vector& vector )
			{	return( (*this) = (*this) + vector );
			}
			const Plane operator - ( const Vector& vector ) const
			{	return( Plane(Normal, Distance - vector % Normal) );
			}
			const Plane& operator -= ( const Vector& vector )
			{	return( (*this) = (*this) - vector );
			}

			// Just your average plane functions
			const bool inline PointOnPlane( const Vector& point ) const
			{
				return( DistanceToPlane(point) == 0 );
			}
			const float inline DistanceToPlane( const Vector& point ) const
			{
				return( Normal % point + Distance );
			}
			const Vector inline RayIntersection( const Vector& rayPos, const Vector& rayDir ) const
			{
				const float a = Normal % rayDir;
				if( a == 0 )
					return( rayPos );	// error line parallel to plane
				
				return( rayPos - rayDir * (DistanceToPlane(rayPos) / a) );
			}
		};

	}
}

#endif // _SHARED_MATH_PLANE_H_
